/**
 * @UiButton.cpp
 * Copyright 2013 (C) FatalEror / Dean Bahari
 * 
 * UiPack is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * See LICENSE file in main folder for more information.
 */

#include "UiCommon.hpp"
#include "UiApp.hpp"
#include "UiBase.hpp"
#include "UiButton.hpp"
#include "UiResource.hpp"

UiButton::UiButton(const wchar_t *text)
{
	mText     = text;
	mCallback = NULL;
	mType     = 0;
	mImage    = NULL;
}

UiButton::UiButton(UiBase *parent, const wchar_t *text, unsigned int width, unsigned int height, int x, int y)
{
	mText     = text;
	mCallback = NULL;
	mType     = 0;
	mImage    = NULL;

	parent->addChild(this);
	this->setPosition(x, y);
	this->setSize(width, height);
	ShowWindow(this->getHandle(), SW_SHOWDEFAULT);
}

UiButton::~UiButton()
{
	if (mImage)
		delete mImage;
}

Gdiplus::Image *UiButton::getImage()
{
	return mImage;
}

const wchar_t *UiButton::getText()
{
	return mText.c_str();
}

void UiButton::setCallback(void *callback, void *param)
{
	mCallback = callback;
	mParam    = param;
}

void UiButton::setImage(const wchar_t *imageDir)
{
	mImage = new Gdiplus::Image(imageDir);
	if (mImage->GetLastStatus() == Gdiplus::OutOfMemory) {
		delete mImage;
		mImage = UiResource::loadImage(imageDir);
	}
	mType  |= UiControl::UI_IMAGE;
}

void UiButton::onClick(UiEvent &ev)
{
	if ((ev.getState() & (UiEvent::UI_MOUSE_CLICK | UiEvent::UI_MOUSE_LEFT)) || (ev.getState() & (UiEvent::UI_MOUSE_RELEASE | UiEvent::UI_MOUSE_LEFT))) {
		InvalidateRect(this->getHandle(), NULL, false);
		if (mCallback && this->getState() & UiControl::UI_SELECTED) {
			RECT rc;
			POINT pt;
			GetWindowRect(this->getHandle(), &rc);
			GetCursorPos(&pt);
			if (PtInRect(&rc, pt)) {
				this->setState(0);
				UpdateWindow(this->getHandle());
				reinterpret_cast<void(*)(void*)>(mCallback)(mParam);
			}
		}
	}
}

void UiButton::onEnter(UiEvent &ev)
{
	InvalidateRect(this->getHandle(), NULL, false);
}

void UiButton::onLeave(UiEvent &ev)
{
	InvalidateRect(this->getHandle(), NULL, false);
}

void UiButton::onPaint(UiEvent &ev)
{
	Gdiplus::Graphics grBuffer(ev.getDC());
	Gdiplus::Image *imgButton = NULL;

	if (this->getState() & UiControl::UI_SELECTED)
		imgButton = UiApp::getResource()->getImage(UiResource::UI_IMAGE_BTN_CLICK);
	else if (this->getState() & UiControl::UI_HOVERED)
		imgButton = UiApp::getResource()->getImage(UiResource::UI_IMAGE_BTN_HOVER);
	else
		imgButton = UiApp::getResource()->getImage(UiResource::UI_IMAGE_BTN_NORMAL);

	unsigned short width = this->getWidth();
	unsigned short height = this->getHeight();

	// TL - TM - TR
	grBuffer.DrawImage(imgButton, Gdiplus::Rect(0, 0, 11, 4), 0, 0, 11, 4, Gdiplus::UnitPixel);
	grBuffer.DrawImage(imgButton, Gdiplus::Rect(11, 0, width, 4), 11, 0, 1, 4, Gdiplus::UnitPixel);
	grBuffer.DrawImage(imgButton, Gdiplus::Rect(width - 11, 0, 11, 4), 11, 0, 11, 4, Gdiplus::UnitPixel);

	// CL - CM - CR
	grBuffer.DrawImage(imgButton, Gdiplus::Rect(0, 4, 11, height - 8), 0, 4, 11, 14, Gdiplus::UnitPixel);
	grBuffer.DrawImage(imgButton, Gdiplus::Rect(11, 4, width - 22, height - 8), 11, 4, 1, 14, Gdiplus::UnitPixel);
	grBuffer.DrawImage(imgButton, Gdiplus::Rect(width - 11, 4, 11, height - 8), 11, 4, 11, 14, Gdiplus::UnitPixel);

	// BL - BM - BR
	grBuffer.DrawImage(imgButton, Gdiplus::Rect(0, height - 4, 11, 4), 0, 18, 11, 4, Gdiplus::UnitPixel);
	grBuffer.DrawImage(imgButton, Gdiplus::Rect(11, height - 4, width, 4), 11, 18, 1, 4, Gdiplus::UnitPixel);
	grBuffer.DrawImage(imgButton, Gdiplus::Rect(width - 11, height - 4, 11, 4), 11, 18, 11, 4, Gdiplus::UnitPixel);

	if (mImage)
		grBuffer.DrawImage(mImage, Gdiplus::Rect(width * 5 / 100, height * 5 / 100 + (this->getState() & UiControl::UI_SELECTED ? 1 : 0), width * 90 / 100, height * 90 / 100), 0, 0, mImage->GetWidth(), mImage->GetHeight(), Gdiplus::UnitPixel);
	else {
		Gdiplus::GraphicsPath path;
		
		Gdiplus::StringFormat sf;
		sf.SetAlignment(Gdiplus::StringAlignmentCenter);
		sf.SetLineAlignment(Gdiplus::StringAlignmentCenter);
		if (this->getState() & UiControl::UI_SELECTED)
			path.AddString(mText.c_str(), -1, UiApp::getResource()->getFont(), Gdiplus::FontStyleRegular, 12, Gdiplus::PointF(this->getWidth() / 2.0f, this->getHeight() / 2.0f + 1), &sf);
		else
			path.AddString(mText.c_str(), -1, UiApp::getResource()->getFont(), Gdiplus::FontStyleRegular, 12, Gdiplus::PointF(this->getWidth() / 2.0f, this->getHeight() / 2.0f), &sf);
		grBuffer.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
		grBuffer.DrawPath(UiApp::getResource()->getPen(UiResource::UI_PEN_TEXT), &path);
		grBuffer.FillPath(UiApp::getResource()->getBrush(UiResource::UI_BRUSH_TEXT), &path);
		grBuffer.SetSmoothingMode(Gdiplus::SmoothingModeNone);
	}
}